﻿<!--对象选择组件-->
<link href="/UI/css/components/components.min.css" rel="stylesheet" />
<template>
    <div class="v-obj-slctor" @click.stop.captch="on_focus" :class="{InputItem:search,Selector:!search,active:!close,disabled:disabled}" :tip="(search&&slcted.length==0)?'':(slcted.length>0?(slcted[0].title||slcted[0].info||slcted.name):'')">
        <div class="vos-tags">
            <template>
                <template v-for="(s,idx) in slcted">
                    <div v-if="!slcted_templ" class="vos-tag" :class="{singleResult:!search||(!multi&&slcted.length==1)}" :tip="s.info||s.title||s.name">
                        {{s.info||s.title||s.name}}
                        <i class="soicon icon-clear" @click.stop="unslct(idx)"></i>
                    </div>
                    <div v-else class="vos-tag" :tip="s.info||s.title||s.name||s">
                        <slct-item :obj="s"></slct-item>
                        <i class="soicon icon-clear" @click.stop="unslct(idx)"></i>
                    </div>
                </template>
            </template>
            <input v-if="search&&(multi||slcted.length<1)" class="key-inputer" @click="on_focus" @focus="on_focus" @blur="on_blur" :placeholder="slcted.length==0?placeholder:''" :disabled="disabled" v-model="keyword" @keydown.delete="del" @keydown.up="go(-1)" @keydown.down="go(1)" @keydown.enter="godone" />
        </div>
        <ul class="vos-options" :class="{withbord:search}">
            <li class="vos-onloading" v-show="src.length==0">
                <div v-if="keyword.length<2">请输入至少2个字开始搜索</div>
                <div v-else>
                    <div class="loading">
                        正在搜索...
                    </div>
                </div>
            </li>
            <template v-if="!view_templ">
                <li v-for="(p,idx) in src" :class="{_slcted:src[idx]._slcted==true,hot:sIdx==idx}" @click.stop="slct(idx)" v-show="!p.hasOwnProperty('_unmatch')||true!==p._unmatch">
                    {{p.info||p.title||p.name}}
                </li>
            </template>
            <template v-else>
                <li v-for="(p,idx) in src" :class="{_slcted:src[idx]._slcted==true,hot:sIdx==idx}" @click.stop="slct(idx)" v-show="!p.hasOwnProperty('_unmatch')||true!==p._unmatch">
                    <view-item :obj="p"></view-item>
                </li>
            </template>
        </ul>
    </div>
</template>
<script>
    vm = {
        props: {
            placeholder: {
                type: String,
                default: '请输入或选择'
            },
            view_templ: {
                type: String,
                default: ''
            },
            slcted_templ: {
                type: String,
                default: ''
            },
            reset: {
                type: Number,
                default: -1
            },
            search: {
                type: Boolean,
                default: true
            },
            src: {
                type: Array,
                default: []
            },
            dynamic_src: {
                type: Boolean,
                default: false
            },
            key_on: {
                type: String,
                default: ''
            },
            freevalue: {
                type: Boolean,
                default: false
            },
            disabled: {
                type: Boolean,
                default: false
            },
            multi: {
                type: Boolean,
                default: true
            },
            parentui: {
                type: LController,
                default: null
            }
        },
        created: function () {
            /*处理自定义显示*/
            if (this.$props.view_templ) {
                var tr = Vue.extend({
                    props: ['obj'],
                    template: this.$props.view_templ.indexOf('#') == 0 ? $(this.$props.view_templ)[0].innerHTML : this.$props.view_templ
                });
                this.$options.components["view-item"] = tr;
            };
            if (this.$props.slcted_templ) {
                var tr = Vue.extend({
                    props: ['obj'],
                    template: this.$props.slcted_templ.indexOf('#') == 0 ? $(this.$props.slcted_templ)[0].innerHTML : this.$props.slcted_templ
                });
                this.$options.components["slcted-item"] = tr;
            };
        },
        mounted: function () {
            var li = $(this.$el).children(".vos-options").eq(0);
            var viewer = $(this.$el).eq(0);
            if (!this.poper) {
                this.poper = new LiberUI.PopPanel(li)
                    .option("AutoPopout", false)
                    .option("AutoHide", true)
                    .PopFor(viewer);
            };
            this.key_inputer = $(this.$el).find('.key-inputer').eq(0);
            if (!this.dynamic_src && this.src.length > 0) {
                this.src.forEach(function (s, i, lst) {
                    if (typeof (s) == 'string') {
                        lst.splice(i, 1, { info: s, _slcted: false, _unmatch: false, _key: s });
                    }
                });
            }
            if (!this.search) {
                this.multi = false;
            }
        },
        beforeUpdate: function () {
            if (!this.dynamic_src && this.src.length > 0) {
                this.src.forEach(function (s, i, lst) {
                    if (typeof (s) == 'string') {
                        lst.splice(i, 1, { info: s, _slcted: false, _unmatch: false, _key: s });
                    }
                });
            }
        },
        data: function () {
            var opt = {
                keyword: '',
                pre_keyword: '',
                slcted: [],
                onloading: false,
                sIdx: -1,
                poper: null,
                focus: true,
                ondeling: null,
                key_inputer: null
            };
            return opt;
        },
        watch: {
            'parentui': function () {
                if (this.parentui && this.parentui.on) {
                    this.parentui.on("hiden", function () { this.poper.hide(); }.bind(this));
                    this.parentui.on("shown", function () { this.options = this.src; }.bind(this));
                };
            },
            'keyword': function (k) {
                k = k.trim();
                if (k.length > this.pre_keyword.length) {
                    this.poper && this.poper.show();
                }
                if (k.length == 0) {
                    this.src.forEach(function (t) {
                        delete t._unmatch;
                    });
                }
                else {
                    if (!this.dynamic_src) {
                        /*非动态数据源，且关键字简单增长，只需在之前的结果中进一步搜索*/
                        this.pre_keyword = k;
                        this.src.forEach(function (t) {
                            if (!t.hasOwnProperty('_unmatch') || t._unmatch === true) {
                                if (!t._key) {
                                    t._key = (t.info || '') + (t.title || '') + (t.name || '');
                                }
                                t._unmatch = t._key.indexOf(k) == -1;
                            }
                        });
                    }
                    else {
                        /*关键字变化，或动态数据源*/
                        this.onloading = true;
                        this.src = [];
                        if (k.length < 2) {
                            return;
                        }
                        var vm = this;
                        this.$emit('src_loading', k, function (nd) {
                            /*匹配已经选中的结果*/
                            if (vm.slcted.length > 0) {
                                nd.forEach(function (t) {
                                    var slctIdx = vm.slcted.findObjIndex(vm.key_on, t[vm.key_on]);
                                    if (slctIdx > -1) {
                                        t._slcted = true;
                                        Vue.set(vm.slcted, slctIdx, t);
                                    }
                                });
                            }
                            this.onloading = false;
                            this.src = nd;;
                        }.bind(this));
                    }
                    this.ondeling = false;
                }
                this.pre_keyword = k;
            },
            'reset': function () {
                this.slcted.forEach(function (s) {
                    s._slcted = false;
                });
                this.slcted = [];
            }
        },
        methods: {
            on_focus: function () {
                this.focus = true;
                this.poper.show();
            },
            on_blur: function (ev, f) {
                this.focus = false;
                if (this.freevalue && this.keyword.trim().length > 0) {
                    this.freeitem(this.keyword.trim());
                }
                this.keyword = '';
                setTimeout(function () {
                    /*延迟200毫秒防止重新获得了焦点*/
                    if (!this.focus) {
                        this.poper.hide();
                    }
                }.bind(this), 200);
            },
            unslct: function (si) {
                if (si > (this.slcted.length - 1)) {
                    return;
                }
                var r = this.slcted[si];
                r._slcted = false;
                this.slcted.splice(si, 1);
                this.$emit('item_unslcted', r);
                this.$emit('value_changed', this.slcted);
            },
            slct: function (idx, keepSidx) {
                if (!keepSidx) {
                    this.sIdx = -1;
                }
                let shouldClose = false;
                if (!this.src[idx]._slcted) {
                    this.src[idx]._slcted = true;
                    this.src[idx]._sidx = idx;
                    if (false === this.multi) {
                        if (this.slcted.length > 0) {
                            this.slcted[0]._slcted = false;
                            this.slcted = [];
                        }
                        shouldClose = true;
                    }
                    this.$emit('item_slcted', this.src[idx]);
                    this.slcted.push(this.src[idx]);
                }
                else {
                    this.src[idx]._slcted = false;
                    this.slcted.splice(this.slcted.findObjIndex('_sidx', idx), 1);
                    this.$emit('item_unslcted', this.src[idx]);
                }
                if (!shouldClose) {
                    this.key_inputer.focus();
                }
                else {
                    this.focus = false;
                    this.pre_keyword = '';
                    this.keyword = '';
                    this.poper && this.poper.hide();
                }
                this.$emit('value_changed', this.slcted);
            },
            godone: function () {
                if (this.sIdx > -1 && this.sIdx < this.src.length) {
                    this.slct(this.sIdx, true);
                }
                else if (this.freevalue && this.keyword.trim().length > 0) {
                    this.freeitem(this.keyword.trim());
                    this.keyword = '';
                }
                else {
                    return;
                }
            },
            go: function (ud) {
                if (ud == -1) {
                    if (this.sIdx > 0) {
                        this.sIdx -= 1;
                    }
                    else {
                        this.sIdx = this.src.length - 1;
                    }
                }
                else {
                    if (this.sIdx < this.src.length - 1) {
                        this.sIdx += 1;
                    }
                    else {
                        this.sIdx = 0;
                    }
                }
                if (this.src[this.sIdx].hasOwnProperty('_unmatch') && this.src[this.sIdx]._unmatch === true) {
                    this.go(ud);
                }
            },
            del: function () {
                if (this.keyword.length > 0 || this.slcted.length == 0) {
                    return;
                }
                if (!this.ondeling) {
                    setTimeout(function () { this.ondeling = true; }.bind(this), 500);
                    setTimeout(function () { this.ondeling = false; }.bind(this), 2000);
                } else {
                    this.unslct(this.slcted.length - 1);
                }
            },
            freeitem: function (k) {
                var s = this.src.findObj('info', k);
                if (!s) {
                    s = {
                        info: k,
                        _slcted: true
                    };
                }
                s._slcted = true;
                this.slcted.push(s);
                this.$emit('item_slcted', s);
                this.$emit('value_changed', this.slcted);
            }
        }
    }
</script>